<?php
namespace hbynlsl\spf;

use hbynlsl\spf\Constant;
use think\facade\Db;

class ResourceModel {
    /**
     * 获取单条数据
     * @param string $resource 资源数据表名称
     * @param string $id 主键id值 
     * @param string $withTables 关联表数据
     */
    public static function find($resource, $id, $withTables = '') {
        // 创建模型类对象
        $model = static::getResourceHandler($resource);
        if (!$model) {
            return static::response('50004');
        }
        // 处理with字段
        if ($withTables) {
            $with = array_map('trim', explode(',', $withTables));
        } else {
            $with = [];
        }
        // 获取单个资源
        if ($id > 0) {
            $datas = $model::with($with)->find($id);
            if (!$datas) {
                return static::response('50005');
            }
            return static::response('10001', $datas, $model::count());
        }
    }

    /**
     * 获取指定资源分页结果集
     * @param string $resource 资源类型
     * @param string $page 当前要显示的页数（默认为1）
     * @param string $where where条件
     * @param string $withTables 关联表数据
     * @param string $fields 字段列表
     * @param string $orderby 排序字段 
     * @param string $pagesize 每一页记录数（默认为10）
     * @return array 返回数据集
     */
    public static function paginate($resource, $page = 1, $where = '', $withTables = '', $fields = '*', $orderby = '', $pagesize = 10) {
        // 创建模型类对象
        $model = static::getResourceHandler($resource);
        if (!$model) {
            return static::response('50004');
        }
        // 处理with字段
        if ($withTables) {
            $with = array_map('trim', explode(',', $withTables));
        } else {
            $with = [];
        }
        // 处理where条件
        $where = static::buildWhere($where);
        // 处理order条件
        $order = static::buildOrder($orderby);
        // 获取分页数据
        $datas = $model::with($with)->where($where)->order($order)->field($fields)->page(intval($page), intval($pagesize))->select();
        // 获取总记录数
        $amount = $model::where($where)->count();
        // 返回
        return static::response('10006', $datas, $amount);
    }

    /**
     * 获取指定资源结果集
     * @param string $resource 资源类型
     * @param string $where where条件
     * @param string $withTables 关联表数据
     * @param string $fields 字段列表
     * @param string $orderby 排序字段 
     * @return array 返回数据集
     */
    public static function select($resource, $where = '', $withTables = '', $fields = '*', $orderby = '') {
        // 创建模型类对象
        $model = static::getResourceHandler($resource);
        if (!$model) {
            return static::response('50004');
        }
        // 处理with字段
        if ($withTables) {
            $with = array_map('trim', explode(',', $withTables));
        } else {
            $with = [];
        }
        // 处理where条件
        $where = static::buildWhere($where);
        // 处理order条件
        $order = static::buildOrder($orderby);
        // 获取数据
        $datas = $model::with($with)->where($where)->order($order)->field($fields)->select();
        // 返回
        return static::response('10002', $datas, $model::count());
    }

    /**
     * 根据order条件构造order表达式
     * @param string $order order条件
     * @return array order表达式数组
     */
    public static function buildOrder($order) {
        // 处理空情况
        if (!$order) {
            return 1;
        }
        // 先按照@分隔多个条件
        $maps = explode('@', $order);
        // 处理每一项条件
        $results = [];
        foreach ($maps as $map) {
            // 按照空格分隔
            $fields = explode(' ', $map);
            // 生成结果
            $results[$fields[0]] = $fields[1];
        }
        // 返回order条件
        return $results;
    }

    /**
     * 根据where条件构造where查询表达式
     * @param string $where where条件
     * @return array where查询表达式数组
     */
    public static function buildWhere($where) {
        // 处理空情况
        if (!$where) {
            return 1;
        }
        // 先按照@分隔多个条件
        $maps = explode('@', $where);
        // 处理每一项条件
        $results = [];
        foreach ($maps as $map) {
            // 按照空格分隔
            $fields = explode(' ', $map);
            // 判断表达式类型
            $op = '=';
            switch ($fields[1]) {
                case 'eq':
                    $op = '=';
                    break;
                case 'neq':
                    $op = '<>';
                    break;
                case 'lt':
                    $op = '<';
                    break;
                case 'gt':
                    $op = '>';
                    break;
                case 'nlt':
                    $op = '>=';
                    break;
                case 'ngt':
                    $op = '<=';
                    break;
                case 'like':
                    $op = 'like';
                    $fields[2] = '%' . $fields[2] . '%';
                    break;
                case 'likel':
                    $op = 'like';
                    $fields[2] = '%' . $fields[2];
                    break;
                case 'liker':
                    $op = 'like';
                    $fields[2] = $fields[2] . '%';
                    break;
                case 'in':
                    $op = 'in';
                    break;
                case 'null':
                    $op = 'exp';
                    $fields[2] = Db::raw(' IS NULL ');
                    break;
                case 'notnull':
                    $op = 'exp';
                    $fields[2] = Db::raw(' IS NOT NULL ');
                    break;
            }
            // 构造查询条件
            $results[] = [$fields[0], $op, $fields[2]];
        }
        // 返回结果
        return $results;
    }

    /**
     * 获取数据表资源操作对象
     * @param string $resource 待操作的数据表名称
     * @param 数据表操作对象
     */
    public static function getResourceHandler($resource) {
        $modelClassName = 'app\models\\' . ucfirst($resource);
        // 判断模型类是否存在
        if (!class_exists($modelClassName)) {
            return false;
        }
        // 返回模型类操作对象
        return $modelClassName;
    }

    protected static function response($status = '10000', $datas = [], $amount = 0) {
        // 返回响应
        return [
            'status'    =>  $status,
            'datas' =>  $datas,
            'amount'    =>  $amount,
            'msg'   =>  Constant::RESPONSE_STATUS[$status]
        ];
    }
}